package com.bucg.cjcloud.gb28181.sip.process;

import com.bucg.cjcloud.gb28181.sip.modle.ResponseModel;
import com.bucg.cjcloud.gb28181.sip.SipServerInfo;
import com.bucg.cjcloud.gb28181.sip.handler.RegisterHandler;
import gov.nist.javax.sip.header.Authorization;
import gov.nist.javax.sip.header.WWWAuthenticate;
import gov.nist.javax.sip.message.SIPRequest;
import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;

import javax.sip.SipProvider;
import javax.sip.address.SipURI;
import javax.sip.address.URI;
import javax.sip.header.AuthorizationHeader;
import javax.sip.header.FromHeader;
import javax.sip.header.HeaderFactory;
import javax.sip.message.MessageFactory;
import javax.sip.message.Request;
import javax.sip.message.Response;

/**
 *
 **/
@Order(1)
@Component
public class RegisterRequestProcess implements RequestProcess {

    @Autowired
    MessageFactory messageFactory;
    @Autowired
    SipProvider sipProvider;

    @Autowired
    HeaderFactory headerFactory;

    @Autowired
    SipServerInfo sipServerInfo;

    @Autowired
    RegisterHandler registerHandler;


    // static Logger LOG = LoggerFactory.getLogger("RegisterRequestProcess");
    static Logger LOG = LoggerFactory.getLogger("RegisterRequestProcess");


    @Override
    public ResponseModel processRequest(Request req, String cmdType) {
        SIPRequest sipReq = (SIPRequest) req;
        Authorization authorization = sipReq.getAuthorization();

        String fromUser = getFromUser(req);
        boolean authorizationResult = false;
        if (sipServerInfo.getPassword() == null || sipServerInfo.getPassword().isEmpty()) {
            if (LOG.isInfoEnabled())
                LOG.info("无需认证");
            authorizationResult = true;
        } else {
            if (authorization == null) {
                WWWAuthenticate wwwAuthenticate = new WWWAuthenticate();
                try {
                    String once = RandomStringUtils.random(10);
                    // wwwAuthenticate.setNonce(once);
                    // wwwAuthenticate.setDomain("3402000000");
                    // wwwAuthenticate.setQop("auth");
                    String s = "Digest realm=\"" + "3402000000" + "\",nonce=\"" + once + "\"";
                    wwwAuthenticate.setScheme(s);
                } catch (Exception e) {
                    e.printStackTrace();
                }

                return ResponseModel.builder().request(req).addHeader(wwwAuthenticate).statusCode(401).build();
                // 验证
            } else {
                if (LOG.isInfoEnabled())
                    LOG.info("第二次注册 register user=" + fromUser);
                // 验证AuthorizationHeader摘要认证信息
                AuthorizationHeader authorizationHeader = (AuthorizationHeader) req.getHeader(AuthorizationHeader.NAME);
                //
                String username = authorizationHeader.getUsername();
                String realm = authorizationHeader.getRealm();
                String nonce = authorizationHeader.getNonce();
                URI uri = authorizationHeader.getURI();
                String res = authorizationHeader.getResponse();
                String algorithm = authorizationHeader.getAlgorithm();
                if (LOG.isInfoEnabled())
                    LOG.info("Authorization：username=" + username + ",realm=" + realm + ",nonce=" + nonce + ",uri=" + uri + ",response=" + res + ",algorithm=" + algorithm);

                if (null == username || null == realm || null == nonce || null == uri || null == res || null == algorithm) {
                    if (LOG.isInfoEnabled())
                        LOG.info("Authorization信息不全，无法认证。");
                } else {
                    String A1 = DigestUtils.md5DigestAsHex((username + ":" + realm + ":" + sipServerInfo.getPassword()).getBytes());
                    String A2 = DigestUtils.md5DigestAsHex(("REGISTER:sip:" + sipServerInfo.getId() + "@" + sipServerInfo.getDomain()).getBytes());
                    String resStr = DigestUtils.md5DigestAsHex((A1 + ":" + nonce + ":" + A2).getBytes());
                    if (resStr.equals(res)) {
                        authorizationResult = true;
                    } else {
                        if (LOG.isInfoEnabled())
                            LOG.info("认证失败");
                        return ResponseModel.builder().request(req).statusCode(Response.FORBIDDEN).build();
                    }
                }

            }
        }
        if (authorizationResult)
            registerHandler.handler(req,fromUser);

        return ResponseModel.builder().
                request(req).
                statusCode(200).
                build();

    }

    private String getFromUser(Request req) {
        FromHeader from = (FromHeader) req.getHeader(FromHeader.NAME);
        SipURI sipURI_from = (SipURI) from.getAddress().getURI();
        return sipURI_from.getUser();
    }

    @Override
    public boolean isSupport(Request req, String cmdType) {

        return "REGISTER".equalsIgnoreCase(req.getMethod());
    }

    // private boolean doTwoRegister(Request request, MessageFactory mf, SipProvider sipProvider, ServerTransaction serverTransactionId, HeaderFactory hf, String toUserId) throws ParseException, SipException, InvalidArgumentException, ParseException, InvalidArgumentException {
    //     Response response;
    //
    //     LOG.info("第二次注册 register user=" + toUserId);
    //     // 验证AuthorizationHeader摘要认证信息
    //     boolean authorizationResult = false;
    //     if (sipServerInfo.getPassword() == null || sipServerInfo.getPassword().isEmpty())
    //         authorizationResult = true;
    //     AuthorizationHeader authorizationHeader = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME);
    //     if (null != authorizationHeader) {//验证
    //         String username = authorizationHeader.getUsername();
    //         String realm = authorizationHeader.getRealm();
    //         String nonce = authorizationHeader.getNonce();
    //         URI uri = authorizationHeader.getURI();
    //         String res = authorizationHeader.getResponse();
    //         String algorithm = authorizationHeader.getAlgorithm();
    //         LOG.info("Authorization：username=" + username + ",realm=" + realm + ",nonce=" + nonce + ",uri=" + uri + ",response=" + res + ",algorithm=" + algorithm);
    //         if (null == username || null == realm || null == nonce || null == uri || null == res || null == algorithm) {
    //             LOG.info("Authorization信息不全，无法认证。");
    //         } else {
    //             String A1 = DigestUtils.md5DigestAsHex((username + ":" + realm + ":" + sipServerInfo.getPassword().getBytes());
    //             String A2 = DigestUtils.md5DigestAsHex(("REGISTER:sip:" + sipServerInfo.getId() + "@" + sipServerInfo.getDomain()).getBytes());
    //             String resStr = DigestUtils.md5DigestAsHex((A1 + ":" + nonce + ":" + A2).getBytes());
    //             if (resStr.equals(res)) {
    //                 authorizationResult = true;
    //             }
    //         }
    //     }
    //     //不管第二次是否成功都移除，失败要从头再来
    //     if (authorizationResult) {
    //         ViaHeader via = (ViaHeader) request.getHeader(ViaHeader.NAME);
    //         response = mf.createResponse(Response.OK, request);
    //         DateHeader dateHeader = hf.createDateHeader(Calendar.getInstance());
    //         response.addHeader(dateHeader);
    //
    //         if (serverTransactionId == null) {
    //             serverTransactionId = sipProvider.getNewServerTransaction(request);
    //             serverTransactionId.sendResponse(response);
    //             return true;
    //         } else {
    //             LOG.info("processRequest serverTransactionId is null.");
    //         }
    //     } else {//注册失败
    //         LOG.info("注册失败");
    //         //返回失败
    //         response = mf.createResponse(Response.FORBIDDEN, request);
    //
    //         if (serverTransactionId == null) {
    //             serverTransactionId = sipProvider.getNewServerTransaction(request);
    //             serverTransactionId.sendResponse(response);
    //         } else {
    //             LOG.info("processRequest serverTransactionId is null.");
    //         }
    //
    //     }
    //     return false;
    // }


}
